﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TempMonitor
{
    class modbus
    {
        public static byte ReadHoldingRegister = 0x3;
        public static byte ReadInputRegister = 0x4;
        public static byte WriteMultipleRegister = 0x10;
        public static byte DeviceAddr = 0;
        public static string PortName = "";
        const byte READ_Holding_Register_LENGTH = 8;
        public static UInt16 Get_Crc_16(byte[] buffer, int len)
        {
            UInt16 wcrc = 0XFFFF;
            byte temp;
            UInt32 i = 0, j = 0;
            for (i = 0; i < len; i++)
            {
                temp = (byte)(buffer[i] & 0xFF);
                wcrc ^= temp;
                for (j = 0; j < 8; j++)
                {
                    if ((wcrc & 0X0001) > 0)
                    {
                        wcrc >>= 1;
                        wcrc ^= 0XA001;
                    }
                    else
                    {
                        wcrc >>= 1;
                    }
                }
            }
            byte CRC_L;
            byte CRC_H;
            CRC_L = (byte)(wcrc & 0xff);
            CRC_H = (byte)(wcrc >> 8);
            return (UInt16)((CRC_L << 8) | CRC_H);
        }

        public static byte[] GetDataForReadHoldingRegister(byte dev_addr, UInt16 reg_start_addr, UInt16 reg_count)
        {
            byte[] data = new byte[READ_Holding_Register_LENGTH];
            data[0] = dev_addr;//地址
            data[1] = ReadHoldingRegister;//功能码
            data[2] = (byte)((reg_start_addr >> 8) & 0xFF);//第一个寄存器的高位地址
            data[3] = (byte)(reg_start_addr & 0xFF);//第一个寄存器的低位地址
            data[4] = (byte)((reg_count >> 8) & 0xFF);
            data[5] = (byte)(reg_count & 0xFF);
            UInt16 checkSum = Get_Crc_16(data, READ_Holding_Register_LENGTH - 2);//校验,2字节
            data[6] = (byte)((checkSum >> 8) & 0xFF);
            data[7] = (byte)(checkSum & 0xFF);

            return data;
        }

        public static byte[] GetDataForReadInputRegister(byte dev_addr, UInt16 reg_start_addr, UInt16 reg_count)
        {
            byte[] data = new byte[READ_Holding_Register_LENGTH];
            data[0] = dev_addr;//地址
            data[1] = ReadInputRegister;//功能码
            data[2] = (byte)((reg_start_addr >> 8) & 0xFF);//第一个寄存器的高位地址
            data[3] = (byte)(reg_start_addr & 0xFF);//第一个寄存器的低位地址
            data[4] = (byte)((reg_count >> 8) & 0xFF);
            data[5] = (byte)(reg_count & 0xFF);
            UInt16 checkSum = Get_Crc_16(data, READ_Holding_Register_LENGTH - 2);//校验,2字节
            data[6] = (byte)((checkSum >> 8) & 0xFF);
            data[7] = (byte)(checkSum & 0xFF);

            return data;
        }

        public static byte[] GetDataForWriteHoldingRegister(byte dev_addr, UInt16 reg_start_addr, UInt16 reg_count, byte data_length, byte[] data)
        {
            UInt16 checkSum = 0;
            byte bufferLength = (byte)(9 + data_length);//固定的9个，加上要发送的数据长度
            byte[] sendData = new byte[bufferLength];

            sendData[0] = dev_addr;//地址
            sendData[1] = WriteMultipleRegister;//功能码
            sendData[2] = (byte)((reg_start_addr >> 8) & 0xFF);//第一个寄存器的高位地址
            sendData[3] = (byte)(reg_start_addr & 0xFF);//第一个寄存器的低位地址
            sendData[4] = (byte)((reg_count >> 8) & 0xFF);//寄存器数量高
            sendData[5] = (byte)(reg_count & 0xFF);//寄存器数量低
            sendData[6] = data_length;//字节数
            for (byte i = 0; i < data_length; i++)
            {
                sendData[7 + i] = data[i];//数据
            }
            checkSum = Get_Crc_16(sendData, bufferLength - 2);//校验,2字节
            sendData[bufferLength - 2] = (byte)((checkSum >> 8) & 0xFF);
            sendData[bufferLength - 1] = (byte)(checkSum & 0xFF);

            return sendData;
        }
    }
}
